/**
 * TorrentJEDI
 * 		Torrent Java Episode Download Interface
 */
package torrentjedi.data;

import java.util.ArrayList;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;

import torrentjedi.core.Configuration;
import torrentjedi.core.SourceConfiguration;
import torrentjedi.core.TorrentSource;

/**
 * @author Alper Kokmen
 *
 */
public class ConfigurationHandler implements ContentHandler {
	/*
	 * used to distinguish the extracted tags from the XML document
	 */
	public static final String TAG_CONFIG = "config";
	public static final String TAG_SOURCE_CONFIG = "source-config";
	
	public static final String TAG_TORRENT_SOURCES = "torrent-sources";
	public static final String TAG_SOURCE = "source";
	public static final String TAG_URL = "url";
	public static final String TAG_NAME = "name";
	public static final String TAG_ICON = "icon";
	public static final String TAG_FAVORITE = "favorite";
	public static final String TAG_UPDATE_INTERVAL = "update-interval";
	public static final String TAG_AUTO_LOAD = "auto-load";
	
	private String data;
	private Integer level;
	private Boolean configTag;
	private Boolean sourceConfigTag;
	private TorrentSource torrentSource;
	
	private Configuration configuration;
	private SourceConfiguration sourceConfiguration;
	
	public ConfigurationHandler(Configuration configuration) {
		super();
		this.configuration = configuration;
	}
	
	public ConfigurationHandler(SourceConfiguration sourceConfiguration) {
		super();
		this.sourceConfiguration = sourceConfiguration;
	}
	
	/**
	 * @return the configuration
	 */
	public Configuration getConfiguration() {
		return configuration;
	}

	/**
	 * @param configuration the configuration to set
	 */
	public void setConfiguration(Configuration configuration) {
		this.configuration = configuration;
	}
	
	/**
	 * @return the data
	 */
	public String getData() {
		return data;
	}

	/**
	 * @param data the data to set
	 */
	public void setData(String data) {
		this.data = data;
	}

	/**
	 * @return the sourceConfiguration
	 */
	public SourceConfiguration getSourceConfiguration() {
		return sourceConfiguration;
	}

	/**
	 * @param sourceConfiguration the sourceConfiguration to set
	 */
	public void setSourceConfiguration(SourceConfiguration sourceConfiguration) {
		this.sourceConfiguration = sourceConfiguration;
	}

	/**
	 * @return the level
	 */
	public Integer getLevel() {
		return level;
	}

	/**
	 * @param level the level to set
	 */
	public void setLevel(Integer level) {
		this.level = level;
	}

	/**
	 * @return the configTag
	 */
	public Boolean getConfigTag() {
		return configTag;
	}

	/**
	 * @param configTag the configTag to set
	 */
	public void setConfigTag(Boolean configTag) {
		this.configTag = configTag;
	}

	/**
	 * @return the sourceConfigTag
	 */
	public Boolean getSourceConfigTag() {
		return sourceConfigTag;
	}

	/**
	 * @param sourceConfigTag the sourceConfigTag to set
	 */
	public void setSourceConfigTag(Boolean sourceConfigTag) {
		this.sourceConfigTag = sourceConfigTag;
	}

	/**
	 * @return the torrentSource
	 */
	public TorrentSource getTorrentSource() {
		return torrentSource;
	}

	/**
	 * @param torrentSource the torrentSource to set
	 */
	public void setTorrentSource(TorrentSource torrentSource) {
		this.torrentSource = torrentSource;
	}

	@Override
	public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
		if (arg2 == 0) {
			System.out.println("WARNING@TorrentJEDI:ConfigurationHandler characters length = 0");
		} else {
			/*
			 * extract the value from the parameters (array, offset, length)
			 * and set the data that is being populated currently (between tags)
			 */
			String value = new String(arg0, arg1, arg2);
			
			if (!value.trim().isEmpty()) {
//				System.out.println("DEBUG@TorrentJEDI:ConfigurationHandler characters level [" + getLevel() + "]");
				
				setData(getData() + value);
			}
		}
	}

	@Override
	public void endDocument() throws SAXException {
//		System.out.println("DEBUG@TorrentJEDI:ConfigurationHandler endDocument");
		
		/*
		 * reset data
		 */
		setData("");
		
		/*
		 * there must be a problem if the level is not 0 at the end of parse operation
		 */
		if (getLevel() != 0) {
			System.out.println("WARNING:TorrentJEDI:ConfigurationHandler endDocument [corrupted config]" + getLevel());
		}
	}

	@Override
	public void endElement(String arg0, String arg1, String arg2)
			throws SAXException {
//		System.out.println("DEBUG@TorrentJEDI:ConfigurationHandler endElement [" + arg1 + "]");
		
//		System.out.println("DEBUG@TorrentJEDI:ConfigurationHandler endElement value [" + getData() + "]");
		
		/*
		 * what are we reading currently? (and of which tag? channel or item?)
		 * after determining that, set the fields properly
		 */
		if (getConfigTag() != null && getConfigTag() == true) {
			if (arg1.equals(TAG_SOURCE_CONFIG)) {
				configuration.setSourceConfigString(getData());
			} else {
				System.out.println("WARNING@TorrentJEDI:ConfigurationHandler endElement [" + arg1 + "] [ignored tag]");
			}
		} else if (getSourceConfigTag() != null && getSourceConfigTag() == true) {
			if (arg1.equals(TAG_SOURCE)) {
				sourceConfiguration.getSources().add(torrentSource);
				setTorrentSource(new TorrentSource());
			} else if (arg1.equals(TAG_NAME)) {
				torrentSource.setName(getData());
			} else if (arg1.equals(TAG_URL)) {
				torrentSource.setUrl(getData());
			} else if (arg1.equals(TAG_ICON)) {
				torrentSource.setIcon(getData());
			} else if (arg1.equals(TAG_FAVORITE)) {
				if (getData().equalsIgnoreCase("YES")) {
					torrentSource.setFavorite(true);	
				} else if (getData().equalsIgnoreCase("NO")) {
					torrentSource.setFavorite(false);
				} else {
					System.out.println("ERROR@TorrentJEDI:ConfigurationHandler endElement [" + arg1 + "] [invalid value for favorite; falling back to false]");
					torrentSource.setFavorite(false);
				}
			} else if (arg1.equals(TAG_AUTO_LOAD)) {
				if (getData().equalsIgnoreCase("YES")) {
					torrentSource.setAutoLoad(true);	
				} else if (getData().equalsIgnoreCase("NO")) {
					torrentSource.setAutoLoad(false);
				} else {
					System.out.println("ERROR@TorrentJEDI:ConfigurationHandler endElement [" + arg1 + "] [invalid value for autoload; falling back to false]");
					torrentSource.setAutoLoad(false);
				}	
			} else if (arg1.equals(TAG_UPDATE_INTERVAL)) {
				try {
					torrentSource.setUpdateInterval(Integer.parseInt(getData()));
				} catch (NumberFormatException e) {
					System.out.println("ERROR@TorrentJEDI:ConfigurationHandler endElement [" + arg1 + "] [invalid value for update interval; falling back to default 10]");
					torrentSource.setUpdateInterval(10);
				}
			} else {
				System.out.println("WARNING@TorrentJEDI:ConfigurationHandler endElement [" + arg1 + "] [ignored tag]");
			}
		} else {
			System.out.println("WARNING@TorrentJEDI:ConfigurationHandler endElement such a config file not supported");
		}
		
		setData("");
		setLevel(getLevel() - 1);
	}

	@Override
	public void endPrefixMapping(String arg0) throws SAXException {
		System.out.println("WARNING@TorrentJEDI:ConfigurationHandler endPrefixMapping [this shouldn't have happened]");

	}

	@Override
	public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
			throws SAXException {
		System.out.println("WARNING@TorrentJEDI:ConfigurationHandler ignorableWhitespace [this shouldn't have happened]");

	}

	@Override
	public void processingInstruction(String arg0, String arg1)
			throws SAXException {
		System.out.println("WARNING@TorrentJEDI:ConfigurationHandler processingInstruction [this shouldn't have happened]");

	}

	@Override
	public void setDocumentLocator(Locator arg0) {
		System.out.println("DEBUG@TorrentJEDI:ConfigurationHandler setDocumentLocator [" + arg0.getSystemId() + "]");

	}

	@Override
	public void skippedEntity(String arg0) throws SAXException {
		System.out.println("WARNING@TorrentJEDI:ConfigurationHandler skippedEntity [this shouldn't have happened]");

	}

	@Override
	public void startDocument() throws SAXException {
//		System.out.println("DEBUG@TorrentJEDI:ConfigurationHandler startDocument");
		
		/*
		 * reset data and level of indentation
		 */
		setData("");
		setLevel(0);
		
		if (sourceConfiguration != null) {
			sourceConfiguration.setSources(new ArrayList<TorrentSource>());
		}
	}

	@Override
	public void startElement(String arg0, String arg1, String arg2,
			Attributes arg3) throws SAXException {
//		System.out.println("DEBUG@TorrentJEDI:ConfigurationHandler startElement [" + arg1 + "]");
		
		/*
		 * reset data and increment level of indentation
		 */
		setData("");
		setLevel(getLevel() + 1);
		
		/*
		 * what tag are we going to be reading?
		 */
		if (arg1.equals(TAG_CONFIG)) {
			setConfigTag(true);
			setSourceConfigTag(false);
		} else if (arg1.equals(TAG_TORRENT_SOURCES)) {
			setTorrentSource(new TorrentSource());
			
			/*
			 * reset channel and item flags
			 */
			setConfigTag(false);
			setSourceConfigTag(true);
		}
	}

	@Override
	public void startPrefixMapping(String arg0, String arg1)
			throws SAXException {
		System.out.println("WARNING@TorrentJEDI:ConfigurationHandler startPrefixMapping [this shouldn't have happened]");

	}

}
